package service

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/cdsailyj/go-vpn/common/tool"
	"gitee.com/cdsailyj/go-vpn/initialize"
	"strconv"
)

var baseUrl = "http://10.72.199.210:8098"

type FaceService struct{}

type BaseResp struct {
	Code    int    `json:"code"`
	Msg     string `json:"msg"`
	Success bool   `json:"success"`
}

type UploadResp struct {
	BaseResp
	Data string `json:"data"`
}

type ManFaceInfoDto struct {
	Id          string  `json:"id"`
	TenantName  string  `json:"tenantName"`
	ManNumber   string  `json:"manNumber"`
	ManName     string  `json:"manName"`
	Sex         string  `json:"sex"`
	PhoneNumber string  `json:"phoneNumber"`
	Mailbox     string  `json:"mailbox"`
	CardNumber  string  `json:"cardNumber"`
	IdCard      string  `json:"idCard"`
	RoomNumber  string  `json:"roomNumber"`
	ImageUrl    string  `json:"imageUrl"`
	Score       float64 `json:"score"`
}

type FaceIdentifyResp struct {
	BaseResp
	Data []ManFaceInfoDto `json:"data"`
}

type FaceInfoListResp struct {
	BaseResp
	Data FaceInfoList `json:"data"`
}

type FaceInfoList struct {
	PageNum  int              `json:"pageNum"`
	PageSize int              `json:"pageSize"`
	Total    int              `json:"total"`
	Pages    int              `json:"pages"`
	List     []ManFaceInfoDto `json:"list"`
}

// 上传人脸图片
func (s *FaceService) UploadImg(imageBytes []byte, field string, filename string) (string, error) {
	if len(imageBytes) < 200 {
		return "", errors.New("人脸图片不合格")
	}
	fileArr := [][]string{{field, filename}}
	bytesArr := [][]byte{imageBytes}
	bytes, status, err := tool.HttpPostMultipart(baseUrl+"/sys/api/v1/minio/uploadFile", fileArr, bytesArr, nil, nil)
	if err != nil || status != 200 {
		return "", errors.New("人脸图片上传到人脸服务失败")
	}

	var uploadResp UploadResp
	err = json.Unmarshal(bytes, &uploadResp)
	if err != nil || len(uploadResp.Data) == 0 {
		return "", errors.New("人脸图片上传到人脸服务失败2")
	}
	return uploadResp.Data, nil
}

// 搜索人脸数据 {keyword  sex  pageNum  pageSize}
func (s *FaceService) FaceInfoList(form map[string]any) (*FaceInfoList, error) {
	var resp FaceInfoListResp
	bytes, status, err := tool.HttpPostJson(baseUrl+"/sys/api/v1/man/info/initPage", form, nil)
	if err != nil || status != 200 {
		return nil, errors.New("查询人脸服务失败")
	}

	err = json.Unmarshal(bytes, &resp)
	if err != nil || resp.Code != 1 {
		return nil, errors.New(fmt.Sprintf("查询人脸服务失败2 %#v \t %#v", err, resp.Msg))
	}
	if resp.Data.Total == 0 {
		return nil, errors.New("查询不到人脸数据")
	}
	return &resp.Data, nil
}

// 人脸识别
func (s *FaceService) FaceIdentify(imageBase64 string) (*ManFaceInfoDto, error) {
	var resp FaceIdentifyResp
	form := map[string]any{"alarmPicture": imageBase64}
	bytes, status, err := tool.HttpPostJson(baseUrl+"/sys/api/v1/man/info/multiSearch/base", form, nil)
	if err != nil || status != 200 {
		return nil, errors.New("人脸识别失败")
	}

	err = json.Unmarshal(bytes, &resp)
	if err != nil || resp.Code != 1 {
		return nil, errors.New(fmt.Sprintf("人脸识别失败2 %#v \t %#v", err, resp.Msg))
	}

	if len(resp.Data) == 0 {
		return nil, errors.New("人脸未匹配到数据")
	}
	return &resp.Data[0], nil
}

// 添加人脸数据
func (s *FaceService) Add(m ManFaceInfoDto) error {
	var resp BaseResp
	bytes, status, err := tool.HttpPostJson(baseUrl+"/sys/api/v1/man/info/btnInsert", m, nil)
	if err != nil || status != 200 {
		return errors.New("人脸添加失败:HttpStatus" + strconv.Itoa(status))
	}

	err = json.Unmarshal(bytes, &resp)
	if err != nil || resp.Code != 1 {
		return errors.New("人脸添加失败2:" + resp.Msg)
	}
	return nil
}

// 修改人脸数据
func (s *FaceService) Update(m ManFaceInfoDto) error {
	var resp BaseResp
	bytes, status, err := tool.HttpPostJson(baseUrl+"/sys/api/v1/man/info/updateInfoByManNumber", m, nil)
	if err != nil || status != 200 {
		return errors.New("人脸修改失败")
	}

	err = json.Unmarshal(bytes, &resp)
	if err != nil || resp.Code != 1 {
		return errors.New("人脸修改失败2:" + resp.Msg)
	}
	return nil
}

// GetFaceByIdCard 通过身份证号码查询唯一
func (s *FaceService) GetFaceByIdCard(idCard string) ([]ManFaceInfoDto, error) {
	form := map[string]any{"keyword": idCard, "pageNum": 1, "pageSize": 1}
	d, e := s.FaceInfoList(form)
	if e != nil {
		return nil, e
	}
	return d.List, nil
}

// SyncFaceInfo 同步人脸数据到系统
func (s *FaceService) SyncFaceInfo(faceUrl string, idCard string, userId string, name string, mobile string, tenantName string) error {
	records, _ := s.GetFaceByIdCard(idCard)
	sex, _ := tool.GetSexByIDCard(idCard)
	if sex == "" {
		sex = "男"
	}
	if records == nil || len(records) == 0 {
		faceInfo := ManFaceInfoDto{
			ManNumber:   idCard,
			IdCard:      idCard,
			TenantName:  tenantName,
			PhoneNumber: mobile,
			ManName:     name,
			CardNumber:  userId,
			ImageUrl:    faceUrl,
			Sex:         sex,
		}
		err := s.Add(faceInfo)

		return err
	} else {
		faceInfo := records[0]
		faceInfo.ImageUrl = faceUrl
		faceInfo.CardNumber = userId
		faceInfo.IdCard = idCard
		faceInfo.ManName = name
		faceInfo.PhoneNumber = mobile
		faceInfo.Sex = sex
		faceInfo.TenantName = tenantName
		err := s.Update(faceInfo)
		return err
	}
}

func (s *FaceService) SetSuccess(id string) (sql.Result, error) {
	db, _ := initialize.GetYwkDB()
	return db.Exec(`UPDATE OUT_CERTIFICATE  SET IS_HANDLE_PHOTO = '1' WHERE  ID = :1`, id)
}

func (s *FaceService) SetFail(id string) (sql.Result, error) {
	db, _ := initialize.GetYwkDB()
	return db.Exec(`UPDATE OUT_CERTIFICATE  SET IS_HANDLE_PHOTO = '1' WHERE  ID = :1`, id)
}

type OutCert struct {
	ID          string `db:"ID" json:"ID" form:"ID"`
	PORTAIT     string `db:"PORTAIT" json:"PORTAIT" form:"PORTAIT"`
	IDCODE      string `db:"IDCODE" json:"IDCODE" form:"IDCODE"`
	USER_ID     string `db:"USER_ID" json:"USER_ID" form:"USER_ID"`
	USER_NAME   string `db:"USER_NAME"  json:"USER_NAME" form:"USER_NAME"`
	OFFICE_NAME string `db:"OFFICE_NAME" json:"OFFICE_NAME" form:"OFFICE_NAME"`
	PDATE       string `db:"PDATE" json:"PDATE" form:"PDATE"`
}

type UserIdCard struct {
	ID              string `db:"ID" json:"ID" form:"ID"`
	ID_CARD_NO      string `db:"ID_CARD_NO" json:"ID_CARD_NO" form:"ID_CARD_NO"`
	NAME            string `db:"NAME" json:"NAME" form:"NAME"`
	MOBILE          string `db:"MOBILE" json:"MOBILE" form:"MOBILE"`
	ENTERPRISE_NAME string `db:"ENTERPRISE_NAME" json:"ENTERPRISE_NAME" form:"ENTERPRISE_NAME"`
	FPATH           string `db:"FPATH" json:"FPATH" form:"FPATH"`
}

func (s *FaceService) GetSignData() ([]UserIdCard, error) {
	var results []UserIdCard
	db, _ := initialize.GetXtkDB()

	sql1 := `SELECT  s.ID, s.ID_CARD_NO, s.NAME, s.MOBILE, s.ENTERPRISE_NAME, u.FPATH FROM APP_USER.USER_FACE_INFO u INNER JOIN APP_USER.SYS_USER s  ON s.id = u.GROUP_ID
	WHERE  u.FPATH is NOT null and s.ID_CARD_NO is not null AND  u.FACE_ID is null
	ORDER BY s.ID ASC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY`

	err := db.Select(&results, sql1)

	//var nameList []string
	//db.Select(&nameList, "SELECT NAME FROM APP_USER.SYS_USER")
	//fmt.Printf("姓名列表：%#v \n", nameList)

	return results, err
}

func (s *FaceService) GetFaceData() ([]OutCert, error) {
	var results []OutCert
	db, _ := initialize.GetYwkDB()
	sqlString := fmt.Sprintf(`
	SELECT ID, PORTAIT, IDCODE, USER_ID, USER_NAME, OFFICE_NAME, PDATE FROM  OUT_CERTIFICATE WHERE  ID in(
		SELECT ID FROM  OUT_CERTIFICATE WHERE IS_HANDLE_PHOTO = 0  and PORTAIT like '%%xpzxothers%%' and DEL_FLAG = '0' AND  IDCODE not in (
			SELECT IDCODE FROM  OUT_CERTIFICATE  WHERE   IS_HANDLE_PHOTO =  '1'
		)
	)
	ORDER BY  PDATE  ASC OFFSET 0  ROWS FETCH NEXT 500 ROWS ONLY
	`)

	//sqlString2 := `SELECT DISTINCT ID, PORTAIT, IDCODE, USER_ID, USER_NAME, OFFICE_NAME, PDATE FROM  OUT_CERTIFICATE WHERE  ID = 'dd2a116c-bbbf-11ed-8add-0c42a18bd6b8'`

	err := db.Select(&results, sqlString)
	if err != nil {
		return nil, err
	}

	return results, nil
}
